/*  Copyright (C) 2009 Jos van der Til
    
    This file is part of the Fluent Metadata Library.

    The Fluent Metadata Library is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    The Fluent Metadata Library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with the Fluent Metadata Library.  If not, see <http://www.gnu.org/licenses/>.
 */
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using FluentMetadata.AttributeBuilders;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace FluentMetadata.Tests.AttributeBuilders.Validation
{
    [TestClass]
    public class RangeAttributeBuilderTest
    {
        [TestMethod]
        public void RangeAttributeBuilder_Supports_Integer_Values()
        {
            var rangeAttribute = RetreiveAttribute(new RangeIntegerTestMetadata());
            Assert.IsNotNull(rangeAttribute);

            Assert.AreEqual(1, rangeAttribute.Minimum);
            Assert.AreEqual(1531, rangeAttribute.Maximum);
        }

        private RangeAttribute RetreiveAttribute(FluentMetadata metadata)
        {
            var attributes = metadata.AttributeBuilders["Value"];

            var rangeAttribute = ((attributes[0] as AbstractAttributeBuilder).GetAttributes().First()) as RangeAttribute;

            return rangeAttribute;
        }

        [TestMethod]
        public void RangeAttributeBuilder_Supports_Double_Values()
        {
            var rangeAttribute = RetreiveAttribute(new RangeDoubleTestMetadata());

            Assert.IsNotNull(rangeAttribute);

            Assert.AreEqual(1D, rangeAttribute.Minimum);
            Assert.AreEqual(15311.101D, (double)rangeAttribute.Maximum, .001);
        }

        [TestMethod]
        public void RangeAttributeBuilder_Supports_Custom_Values()
        {
            var rangeAttribute = RetreiveAttribute(new RangeCustomTestMetadata());

            Assert.IsNotNull(rangeAttribute);

            Assert.AreEqual("1-1-2009",rangeAttribute.Minimum);
            Assert.AreEqual("12-31-2009", rangeAttribute.Maximum);
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void RangeAttributeBuilder_Throws_Exception_When_Used_Incorrectly()
        {
            var attribute = RetreiveAttribute(new RangeIncorrectTestMetadata());
        }

        #region Integer test classes

        class RangeIntegerTest
        {
            public int Value { get; set; }
        }

        class RangeIntegerTestMetadata : FluentMetadata<RangeIntegerTest>
        {
            public RangeIntegerTestMetadata()
            {
                ForProperty(x => x.Value).AddValidation
                    .Range()
                    .Minimum(1).Maximum(1531);
            }
        }

        #endregion

        #region Double test classes
        class RangeDoubleTest
        {
            public double Value { get; set; }
        }

        class RangeDoubleTestMetadata : FluentMetadata<RangeDoubleTest>
        {
            public RangeDoubleTestMetadata()
            {
                ForProperty(x => x.Value).AddValidation
                    .Range()
                    .Minimum(1D).Maximum(15311.101D);
            }
        }
        #endregion

        #region Custom test classes
        class RangeCustomTest
        {
            public DateTime Value { get; set;}
        }

        class RangeCustomTestMetadata : FluentMetadata<RangeCustomTest>
        {
            public RangeCustomTestMetadata()
            {
                ForProperty(x => x.Value).AddValidation.Range()
                    .ForType(typeof (DateTime))
                    .Minimum("1-1-2009")
                    .Maximum("12-31-2009");
            }
        }
        #endregion

        #region Incorrect usage test classes

        class RangeIncorrectTest
        {
            public int Value { get; set; }
        }

        class RangeIncorrectTestMetadata :FluentMetadata<RangeIncorrectTest>
        {
            public RangeIncorrectTestMetadata()
            {
                ForProperty(x => x.Value).AddValidation.Range().Minimum(1.0D).Maximum("10");
            }
        }
        #endregion
    }
}